# -*- coding: utf-8 -*-
__author__ = 'liubei'

from mongoengine import *
import time
from bson.objectid import ObjectId
import hashlib
import aes
import datetime
import pytz
import az_dateutil

class ValidateCode(DynamicDocument):
    validateCode = StringField(required=True)
    userPhone = StringField(required=True)


class SurveyPage(DynamicDocument):
    content = StringField(required=True)
    choices = ListField()
    nextIds = ListField(default=[])
    type = IntField(default=0)


class Token(DynamicDocument):
    userPhone = StringField(required=True)
    accessToken = StringField(required=True)


class Survey(DynamicDocument):
    name = StringField(required=True)
    des = StringField(required=True)
    createdDate = IntField(default=int(time.time()))
    firstNode = StringField(required=True)
    surveies = ListField(ReferenceField(SurveyPage))


class SurveyResult(DynamicDocument):
    surveyId = StringField(required=True)
    name = StringField(required=True)
    des = StringField(required=True)
    createdDate = IntField(required=True)
    surveyResults = ListField()
    userPhone = StringField(required=True)


class SurveyResultOffline(DynamicDocument):
    surveyId = StringField(required=True)
    name = StringField(required=True)
    des = StringField(required=True)
    createdDate = IntField(required=True)
    surveyResults = ListField()
    patientCode = StringField(required=True)


class Medicine(DynamicDocument):
    userPhone = StringField(required=True)
    createDate = IntField(required=True)
    createDateString = StringField()
    done = StringField(required=True)
    remainingMedicine = StringField()


class User(DynamicDocument):
    userPhone = StringField(required=True)
    userBirthday = StringField(required=True)
    userType = IntField(required=True)
    userGender = StringField(required=True)
    nickName = StringField(required=True)
    userHeight = IntField(required=True)
    isSmoke = IntField(required=True)
    hasHighBp = IntField(required=True)
    patientCode = StringField(required=True)
    remainingMedicine = StringField(required=True, default='-1')
    createDate = IntField(default=int(time.time()))


class Caregiver(DynamicDocument):
    #病人手机号
    caredUserPhone = StringField(required=True)
    #看护者手机号
    userPhone = StringField(required=True)
    nickName = StringField(required=True)
    createDate = IntField(default=int(time.time()))
    list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
    #inviteCode 为0，表示邀请码使用
    inviteCode = IntField(required=True)
    shared = IntField(default=0)


host = '0.0.0.0'
# host = 'pi.iccapp.com'
# host = '192.168.8.37'
# host = '192.168.33.10'
# host = '216.89.223.132'
# host = '121.40.213.75'

def querySurveyList():
    connect('az', host=host)
    return Survey.objects()


def querySurveyByName(surveyName):
    connect('az', host=host)
    return Survey.objects(name=surveyName).first()


def queryMedicineList():
    connect('az', host=host)
    return Medicine.objects()


def querySurvey(uid):
    connect('az', host=host)
    return Survey.objects(_id=ObjectId(uid))

def querySurveyByName(name):
    connect('az', host=host)
    return Survey.objects(name=name)[0]

def queryUser(userPhone):
    connect('az', host=host)
    users = User.objects(userPhone=userPhone)
    if users.count() > 0:
        return users[0]


def queryUserByPatientCode(patientCode):
    connect('az', host=host)
    users = User.objects(patientCode=patientCode)
    if users.count() > 0:
        return users[0]


def updateUser(dic):
    connect('az', host=host)
    if dic.has_key('remainingMedicine'):
        return User.objects(userPhone=dic['userPhone']).update(set__patientCode=dic['patientCode'],
                                                               set__isSmoke=dic['isSmoke'],
                                                               set__nickName=dic['nickName'],
                                                               set__userBirthday=dic['userBirthday'],
                                                               set__userHeight=dic['userHeight'],
                                                               set__userGender=dic['userGender'],
                                                               set__hasHighBp=dic['hasHighBp'],
                                                               set__remainingMedicine=dic['remainingMedicine'])
    else:
        return User.objects(userPhone=dic['userPhone']).update(set__patientCode=dic['patientCode'],
                                                               set__isSmoke=dic['isSmoke'],
                                                               set__nickName=dic['nickName'],
                                                               set__userBirthday=dic['userBirthday'],
                                                               set__userHeight=dic['userHeight'],
                                                               set__userGender=dic['userGender'],
                                                               set__hasHighBp=dic['hasHighBp'])


def updateUserRemainMedicine(remainingMedicine, userPhone):
    connect('az', host=host)
    return User.objects(userPhone=userPhone).update(set__remainingMedicine=remainingMedicine)


def queryUserById(uid):
    connect('az', host=host)
    return User.objects(_id = ObjectId(uid))[0]


def querySurveyPage(uid):
    connect('az', host=host)
    return SurveyPage.objects(_id = ObjectId(uid))

def createSurvey():
    connect('az', host=host)
    surveyPage1 = SurveyPage(content='问卷调查第一题', choices=['经常', '不经常']).save()
    surveyPage2 = SurveyPage(content='问卷调查第二题', choices=['经常', '不经常']).save()
    survey = Survey(name='name', des='这是一份来自xx的问卷调查', surveies=[surveyPage1, surveyPage2]).save()
    # survey.save()


def createSurveyResult(dic):
    connect('az', host=host)
    survey = querySurvey(dic['uid'])[0]
    if survey == None:
        return False
    surveyResults = dic['surveyResult']
    surveyResultsList = []
    aes_cipher = aes.AESCipher(aes.aes_key)
    for surveyResult in surveyResults:
        surveyPage = querySurveyPage(surveyResult['uid'])
        if surveyPage.count() > 0:
            if surveyPage[0].type == 0:
                surveyResultTmpDic = {}
                surveyResultTmpDic['uid'] = str(surveyPage[0].id)
                surveyResultTmpDic['choice'] = aes_cipher.encrypt(surveyPage[0].choices[int(surveyResult['choice'])].encode('utf-8'))
                surveyResultsList.append(surveyResultTmpDic)
            else:
                surveyResultTmpDic = {}
                surveyResultTmpDic['uid'] = str(surveyPage[0].id)
                surveyResultTmpDic['choice'] = aes_cipher.encrypt(surveyResult['choice'])
                surveyResultsList.append(surveyResultTmpDic)
        else:
            return False
    #过滤已经提交过了问卷的情况，过滤依据，两份问卷相隔时间1天以内，都作为是做更新操作；1天以上，作为新建
    #依据：两份相同名字的问卷，可以允许回答的时间至少在几天以上
    now = time.time()
    updateAction = False
    surveyResults = SurveyResult.objects(name=survey.name, userPhone=dic['userPhone'])
    for surveyResult in surveyResults:
        if abs(now - surveyResult.createdDate) < 24 * 60 * 60:
            updateAction = True
            break
    if updateAction:
        #忽略更新操作
        print 'ignore insert'
        pass
    else:
        surveyResult = SurveyResult(surveyId=str(survey.id), name=survey.name, des=survey.des, surveyResults=surveyResultsList, userPhone=dic['userPhone'], createdDate=int(time.time())).save()
        surveyResult.save()
    return True


def createMedicine(dic):
    connect('az', host=host)
    medicines = Medicine.objects(userPhone=dic['userPhone'])
    needUpdate = True
    aes_cipher = aes.AESCipher(aes.aes_key)
    if medicines.count() == 0:
        print 'not find cholesterol'
        medicine = Medicine(userPhone=dic['userPhone'], createDate=dic['createDate'], done=aes_cipher.encrypt(dic['done']))
        return (str(medicine.save().id), needUpdate)
    for medicine in medicines:
        cTimeLong = medicine.createDate
        cTime = time.strftime('%Y-%m-%d', time.localtime(cTimeLong))
        now = int(dic['createDate'])
        nTime = time.strftime('%Y-%m-%d', time.localtime(now))
        if cTime == nTime:
            print 'update today cholesterol'
            if int(aes_cipher.decrypt(medicine.done)) == int(dic['done']):
                needUpdate = False
            if int(dic['done']) == 0:
                Medicine.objects(id=medicine.id).update(set__userPhone=dic['userPhone'],
                                                        set__done=aes_cipher.encrypt(0))
            else:
                Medicine.objects(id=medicine.id).update(set__done=aes_cipher.encrypt(1),
                                                        set__createDate=dic['createDate'],
                                                        set__userPhone=dic['userPhone'])
            return (str(medicine.id), needUpdate)
    print 'not find today cholesterol'

    medicine = Medicine(userPhone=dic['userPhone'], createDate=dic['createDate'], done=aes_cipher.encrypt(dic['done']))
    return (str(medicine.save().id), needUpdate)


#多线程
def createMedicineFix(dic):
    connect('az', host=host)
    tz = pytz.timezone(pytz.country_timezones('cn')[0])
    cTime = datetime.datetime.fromtimestamp(float(dic['createDate']), tz).strftime("%Y-%m-%d")
    thisDate = datetime.datetime.fromtimestamp(float(dic['createDate']), tz)
    thisTime = int(az_dateutil.date2timestamp(thisDate.replace(thisDate.year, thisDate.month, thisDate.day, 0, 0, 0)))

    medicine = Medicine.objects(userPhone=dic['userPhone'],
                                                   createDate__gte=thisTime-8*60*60,
                                                   createDate__lt=thisTime+16*60*60).first()
    aes_cipher = aes.AESCipher(aes.aes_key)
    needUpdate = True
    if medicine == None:
        medicine = Medicine(userPhone=dic['userPhone'], createDate=dic['createDate'],
                            done=aes_cipher.encrypt(dic['done']), createDateString=cTime)
        return (str(medicine.save().id), needUpdate)
    else:
        if int(aes_cipher.decrypt(medicine.done)) == int(dic['done']):
            needUpdate = False
        if int(dic['done']) == 0:
            Medicine.objects(id=medicine.id).update(set__userPhone=dic['userPhone'],
                                                    set__done=aes_cipher.encrypt(0))
        else:
            Medicine.objects(id=medicine.id).update(set__done=aes_cipher.encrypt(1),
                                                    set__createDate=dic['createDate'],
                                                    set__userPhone=dic['userPhone'])
        return (str(medicine.id), needUpdate)


def deleteMedicine(uid):
    connect('az', host=host)
    medicine = Medicine.objects(_id=ObjectId(uid))
    medicine.update(set__done=0, set__remainingMedicine=int(medicine[0].remainingMedicine)+1)


def queryMedicineListByParam(phone, page=0, pageSize=10, done=1):
    connect('az', host=host)
    medicineDic = {}
    medicineList = []
    user = queryUser(phone)
    aes_cipher = aes.AESCipher(aes.aes_key)
    if done == 1:
        if page < 0:
            medicines = Medicine.objects(userPhone=phone).order_by('-createDate')
            medicines = filterMedicine(medicines, done, aes_cipher)
        else:
            medicines = Medicine.objects(userPhone=phone).order_by('-createDate')[page * pageSize:pageSize]
            medicines = filterMedicine(medicines, done, aes_cipher)
    else:
        if page < 0:
            medicines = Medicine.objects(userPhone=phone).order_by('-createDate')
        else:
            medicines = Medicine.objects(userPhone=phone).order_by('-createDate')[page * pageSize:pageSize]
    for medicine in medicines:
        medicineTmpDic = {}
        medicineTmpDic['uid'] = str(medicine.id)
        medicineTmpDic['createDate'] = medicine.createDate
        medicineTmpDic['remainingMedicine'] = aes_cipher.decrypt(user.remainingMedicine)
        medicineTmpDic['done'] = aes_cipher.decrypt(medicine.done)
        medicineList.append(medicineTmpDic)
    medicineDic['medicines'] = medicineList
    medicineDic['page'] = page
    medicineDic['total'] = medicines.count()
    return medicineDic

def filterMedicine(medicines, done, aes_cipher):
    tmpMedicines = []
    for medicine in medicines:
        if int(aes_cipher.decrypt(medicine.done)) == int(done):
            tmpMedicines.append(medicine)
    return tmpMedicines

def queryMedicineByCreateDate(createDate, userPhone):
    connect('az', host=host)
    medicines = Medicine.objects(userPhone=userPhone)
    for medicine in medicines:
        cTimeLong = medicine.createDate
        cTime = time.strftime('%Y-%m-%d', time.localtime(cTimeLong))
        now = int(createDate)
        nTime = time.strftime('%Y-%m-%d', time.localtime(now))
        if cTime == nTime:
            return str(medicine.id)


def createCaregiver(dic):
    connect('az', host=host)
    caregiver = Caregiver(caredUserPhone=dic['caredUserPhone'], userPhone=dic['userPhone'], nickName=dic['nickName'], inviteCode=dic['inviteCode'])
    caregiver.save()


def updateCaregiver(dic):
    connect('az', host=host)
    Caregiver.objects(caredUserPhone=dic['caredUserPhone'], userPhone=dic['userPhone']).update(set__nickName=dic['nickName'], set__inviteCode=dic['inviteCode'], set__createDate=int(time.time()))


def updateCaregiverByUid(uid, shared):
    connect('az', host=host)
    Caregiver.objects(_id=ObjectId(uid)).update(set__shared=shared)


def updateCaregiverByInviteCode(uid):
    connect('az', host=host)
    Caregiver.objects(_id=ObjectId(uid)).update(set__inviteCode=0, set__shared=1)


def queryCaregivers():
    connect('az', host=host)
    return Caregiver.objects()


def queryCaregiversByCaredUserPhone(caredUserPhone):
    connect('az', host=host)
    return Caregiver.objects(caredUserPhone=caredUserPhone).order_by('-createDate')


def queryCaregiverByPhone(caredUserPhone, userPhone):
    connect('az', host=host)
    return Caregiver.objects(caredUserPhone=caredUserPhone, userPhone=userPhone)


def queryCaregiverByPhoneAndInviteCode(userPhone, inviteCode):
    connect('az', host=host)
    return Caregiver.objects(inviteCode=inviteCode, userPhone=userPhone)


def queryCaregiverSharedByPhone(userPhone):
    connect('az', host=host)
    return Caregiver.objects(userPhone=userPhone, shared=1, inviteCode=0)


def queryUserListByParam(page=0, pageSize=10):
    connect('az', host=host)
    medicineDic = {}
    medicineList = []
    if page<0:
        users = User.objects()
    else:
        users = User.objects()[page * pageSize:pageSize]
    for user in users:
        medicineTmpDic = {}
        medicineTmpDic['uid'] = str(user.id)
        medicineTmpDic['userPhone'] = user.userPhone
        medicineTmpDic['userType'] = user.userType
        medicineTmpDic['userBirthday'] = user.userBirthday
        medicineTmpDic['userHeight'] = user.userHeight
        medicineTmpDic['nickName'] = user.nickName
        medicineTmpDic['userGender'] = user.userGender
        medicineList.append(medicineTmpDic)
    medicineDic['users'] = medicineList
    medicineDic['page'] = page
    medicineDic['total'] = users.count()
    return medicineDic


def updateValidate(dic):
    connect('az', host=host)
    ValidateCode.objects(userPhone=dic['userPhone']).update(set__validateCode=dic['validateCode'])


def queryValidateCode(userPhone):
    connect('az', host=host)
    return ValidateCode.objects(userPhone=userPhone)


def createValidateCode(dic):
    connect('az', host=host)
    validateCode = ValidateCode(userPhone=dic['userPhone'], validateCode=dic['validateCode'])
    validateCode.save()


def deleteToken(accessToken):
    connect('az', host=host)
    Token.objects(accessToken=accessToken).delete()


def updateUserPwd():
    connect('az', host=host)
    users = User.objects()
    for user in users:
        print user.userPwd
        user.update(set__userPwd = hashlib.md5(user.userPwd).hexdigest().upper())


if __name__ == "__main__":
    # createSurvey()
    # surveies = querySurveyList()
    # print surveies[0]
    # print querySurvey('54a3bca2b2c67d4ab03ee148')
    # print ''.join(random.sample(['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'], 6))
    # deleteToken("XhPeIAZMklySvusj")
    # updateUser()
    connect('az', host=host)
    # users = User.objects()
    # for user in users:
    #     user.update(set__createDate=int(time.time()))
    # connect('az', host=host)
    # articles = SurveyPage.objects()
    # for article in articles:
    #     ids = []
    #     for id in article.nextIds:
    #         ids.append(str(id))
    #     print ids
    #     article.update(set__nextIds = ids)
    # pass
    # msgs = topic.LongMsgStrategy.objects()
    # for model in msgs:
    #     print model.isSmoke
    #     print model.day
    #     print model.msg_no

    # print topic.queryLongMsgStrategy(0, 0)
    # print 1006 in topic.queryQuestionStrategy(1, 0)[0].quiz_nos
    # users = User.objects()
    # for user in users:
    #     medicineDic = queryMedicineListByParam(user.userPhone, 0, 1, 0)
    #     if len(medicineDic['medicines'])>0:
    #         remainingMedicine = medicineDic['medicines'][0]['remainingMedicine']
    #         print "userphoen: " + user.userPhone + " remainingMedicine " + str(remainingMedicine)
    #         updateUserRemainMedicine(remainingMedicine, user.userPhone)